package com.xxl.api.admin.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.core.type.TypeReference;
import com.xxl.api.admin.core.consistant.FieldTypeEnum;
import com.xxl.api.admin.core.model.ReturnT;
import com.xxl.api.admin.core.model.XxlApiBiz;
import com.xxl.api.admin.core.model.XxlApiDataType;
import com.xxl.api.admin.core.model.XxlApiDataTypeField;
import com.xxl.api.admin.core.model.XxlApiDocument;
import com.xxl.api.admin.core.model.XxlApiUser;
import com.xxl.api.admin.core.util.ApiDataTypeToCode;
import com.xxl.api.admin.core.util.JacksonUtil;
import com.xxl.api.admin.dao.IXxlApiBizDao;
import com.xxl.api.admin.dao.IXxlApiDataTypeDao;
import com.xxl.api.admin.dao.IXxlApiDataTypeFieldDao;
import com.xxl.api.admin.dao.IXxlApiDocumentDao;
import com.xxl.api.admin.service.IXxlApiDataTypeService;
import com.xxl.api.admin.service.impl.LoginService;

/**
 * Created by xuxueli on 17/5/23.
 */
@Controller
@RequestMapping("/datatype")
public class XxlApiDataTypeController {
	@Resource
	private IXxlApiDataTypeDao xxlApiDataTypeDao;
	@Resource
	private IXxlApiDataTypeFieldDao xxlApiDataTypeFieldDao;
	@Resource
	private IXxlApiBizDao xxlApiBizDao;
	@Resource
	private IXxlApiDocumentDao xxlApiDocumentDao;
	@Resource
	private IXxlApiDataTypeService xxlApiDataTypeService;

	@RequestMapping
	public String index(Model model) {
		// 业务线列表
		List<XxlApiBiz> bizList = xxlApiBizDao.loadAll();
		model.addAttribute("bizList", bizList);
		return "datatype/datatype.list";
	}

	@RequestMapping("/pageList")
	@ResponseBody
	public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
			@RequestParam(required = false, defaultValue = "10") int length, int bizId, String name) {
		// page list
		List<XxlApiDataType> list = xxlApiDataTypeDao.pageList(start, length, bizId, name);
		int count = xxlApiDataTypeDao.pageListCount(start, length, bizId, name);
		// package result
		Map<String, Object> maps = new HashMap<String, Object>();
		maps.put("recordsTotal", count); // 总记录数
		maps.put("recordsFiltered", count); // 过滤后的总记录数
		maps.put("data", list); // 分页列表
		return maps;
	}

	private boolean hasBizPermission(HttpServletRequest request, int bizId) {
		XxlApiUser loginUser = (XxlApiUser) request.getAttribute(LoginService.LOGIN_IDENTITY);
		if (loginUser.getType() == 1
				|| ArrayUtils.contains(StringUtils.split(loginUser.getPermissionBiz(), ","), String.valueOf(bizId))) {
			return true;
		} else {
			return false;
		}
	}

	@RequestMapping("/addDataTypePage")
	public String addDataTypePage(Model model) {
		// 业务线列表
		List<XxlApiBiz> bizList = xxlApiBizDao.loadAll();
		model.addAttribute("bizList", bizList);
		return "datatype/datatype.add";
	}

	@RequestMapping("/addDataType")
	@ResponseBody
	public ReturnT<Integer> addDataType(HttpServletRequest request, XxlApiDataType apiDataTypeDTO,
			String fieldTypeJson) {
		// parse json field
		if (StringUtils.isNotBlank(fieldTypeJson)) {
			List<XxlApiDataTypeField> fieldList = JacksonUtil.readValueRefer(fieldTypeJson,
					new TypeReference<List<XxlApiDataTypeField>>() {
					});
			if (CollectionUtils.isNotEmpty(fieldList)) {
				apiDataTypeDTO.setFieldList(fieldList);
			}
		}
		// valid datatype
		if (StringUtils.isBlank(apiDataTypeDTO.getName())) {
			return new ReturnT<Integer>(ReturnT.FAIL_CODE, "数据类型名称不可为空");
		}
		if (StringUtils.isBlank(apiDataTypeDTO.getAbout())) {
			return new ReturnT<Integer>(ReturnT.FAIL_CODE, "数据类型描述不可为空");
		}
		if (!hasBizPermission(request, apiDataTypeDTO.getBizId())) {
			return new ReturnT<Integer>(ReturnT.FAIL_CODE, "您没有相关业务线的权限,请联系管理员开通");
		}
		XxlApiBiz apiBiz = xxlApiBizDao.load(apiDataTypeDTO.getBizId());
		if (apiBiz == null) {
			return new ReturnT<Integer>(ReturnT.FAIL_CODE, "业务线ID非法");
		}
		XxlApiDataType existsByName = xxlApiDataTypeDao.loadByName(apiDataTypeDTO.getName());
		if (existsByName != null) {
			return new ReturnT<Integer>(ReturnT.FAIL_CODE, "数据类型名称不可重复，请更换");
		}
		// valid field
		if (CollectionUtils.isNotEmpty(apiDataTypeDTO.getFieldList())) {
			for (XxlApiDataTypeField field : apiDataTypeDTO.getFieldList()) {
				// valid
				if (StringUtils.isBlank(field.getFieldName())) {
					return new ReturnT<Integer>(ReturnT.FAIL_CODE, "字段名称不可为空");
				}
				XxlApiDataType filedDataType = xxlApiDataTypeService.loadDataType(field.getFieldDatatypeId());
				if (filedDataType == null) {
					return new ReturnT<Integer>(ReturnT.FAIL_CODE, "字段数据类型ID非法");
				}
				if (FieldTypeEnum.match(field.getFieldType()) == null) {
					return new ReturnT<Integer>(ReturnT.FAIL_CODE, "字段形式非法");
				}
			}
		}
		// add datatype
		int addRet = xxlApiDataTypeDao.add(apiDataTypeDTO);
		if (addRet < 1) {
			return new ReturnT<Integer>(ReturnT.FAIL_CODE, "数据类型新增失败");
		}
		if (CollectionUtils.isNotEmpty(apiDataTypeDTO.getFieldList())) {
			for (XxlApiDataTypeField field : apiDataTypeDTO.getFieldList()) {
				field.setParentDatatypeId(apiDataTypeDTO.getId());
			}
			// add field
			int ret = xxlApiDataTypeFieldDao.add(apiDataTypeDTO.getFieldList());
			if (ret < 1) {
				return new ReturnT<Integer>(ReturnT.FAIL_CODE, "数据类型新增失败");
			}
		}
		return apiDataTypeDTO.getId() > 0 ? new ReturnT<Integer>(apiDataTypeDTO.getId())
				: new ReturnT<Integer>(ReturnT.FAIL_CODE, "");
	}

	@RequestMapping("/updateDataTypePage")
	public String updateDataTypePage(HttpServletRequest request, Model model, int dataTypeId) {
		XxlApiDataType apiDataType = xxlApiDataTypeService.loadDataType(dataTypeId);
		if (apiDataType == null) {
			throw new RuntimeException("数据类型ID非法");
		}
		model.addAttribute("apiDataType", apiDataType);
		if (!hasBizPermission(request, apiDataType.getBizId())) {
			throw new RuntimeException("您没有相关业务线的权限,请联系管理员开通");
		}
		// 业务线列表
		List<XxlApiBiz> bizList = xxlApiBizDao.loadAll();
		model.addAttribute("bizList", bizList);
		return "datatype/datatype.update";
	}

	@RequestMapping("/updateDataType")
	@ResponseBody
	public ReturnT<String> updateDataType(HttpServletRequest request, XxlApiDataType apiDataTypeDTO,
			String fieldTypeJson) {
		// parse json field
		if (StringUtils.isNotBlank(fieldTypeJson)) {
			List<XxlApiDataTypeField> fieldList = JacksonUtil.readValueRefer(fieldTypeJson,
					new TypeReference<List<XxlApiDataTypeField>>() {
					});
			if (CollectionUtils.isNotEmpty(fieldList)) {
				apiDataTypeDTO.setFieldList(fieldList);
			}
		}
		// valid datatype
		if (StringUtils.isBlank(apiDataTypeDTO.getName())) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "数据类型名称不可为空");
		}
		if (StringUtils.isBlank(apiDataTypeDTO.getAbout())) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "数据类型描述不可为空");
		}
		if (!hasBizPermission(request, apiDataTypeDTO.getBizId())) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "您没有相关业务线的权限,请联系管理员开通");
		}
		XxlApiBiz apiBiz = xxlApiBizDao.load(apiDataTypeDTO.getBizId());
		if (apiBiz == null) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "业务线ID非法");
		}
		XxlApiDataType existsByName = xxlApiDataTypeDao.loadByName(apiDataTypeDTO.getName());
		if (existsByName != null && existsByName.getId() != apiDataTypeDTO.getId()) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "数据类型名称不可重复，请更换");
		}
		// valid field
		if (CollectionUtils.isNotEmpty(apiDataTypeDTO.getFieldList())) {
			for (XxlApiDataTypeField field : apiDataTypeDTO.getFieldList()) {
				// valid
				if (StringUtils.isBlank(field.getFieldName())) {
					return new ReturnT<String>(ReturnT.FAIL_CODE, "字段名称不可为空");
				}
				XxlApiDataType filedDataType = xxlApiDataTypeDao.load(field.getFieldDatatypeId());
				if (filedDataType == null) {
					return new ReturnT<String>(ReturnT.FAIL_CODE, "字段数据类型ID非法");
				}
				if (FieldTypeEnum.match(field.getFieldType()) == null) {
					return new ReturnT<String>(ReturnT.FAIL_CODE, "字段形式非法");
				}
			}
		}
		// update datatype
		int ret1 = xxlApiDataTypeDao.update(apiDataTypeDTO);
		if (ret1 > 0) {
			// remove old, add new
			xxlApiDataTypeFieldDao.deleteByParentDatatypeId(apiDataTypeDTO.getId());
			if (CollectionUtils.isNotEmpty(apiDataTypeDTO.getFieldList())) {
				for (XxlApiDataTypeField field : apiDataTypeDTO.getFieldList()) {
					field.setParentDatatypeId(apiDataTypeDTO.getId());
				}
				int ret = xxlApiDataTypeFieldDao.add(apiDataTypeDTO.getFieldList());
				if (ret < 1) {
					return new ReturnT<String>(ReturnT.FAIL_CODE, "数据类型新增失败");
				}
			}
		}
		return ret1 > 0 ? ReturnT.SUCCESS : ReturnT.FAIL;
	}

	@RequestMapping("/dataTypeDetail")
	public String dataTypeDetail(HttpServletRequest request, Model model, int dataTypeId) {
		XxlApiDataType apiDataType = xxlApiDataTypeService.loadDataType(dataTypeId);
		if (apiDataType == null) {
			throw new RuntimeException("数据类型ID非法");
		}
		model.addAttribute("apiDataType", apiDataType);
		// 业务线列表
		List<XxlApiBiz> bizList = xxlApiBizDao.loadAll();
		model.addAttribute("bizList", bizList);
		// 代码生成
		String codeContent = ApiDataTypeToCode.parseDataTypeToCode(apiDataType);
		model.addAttribute("codeContent", codeContent);
		// 权限
		model.addAttribute("hasBizPermission", hasBizPermission(request, apiDataType.getBizId()));
		return "datatype/datatype.detail";
	}

	@RequestMapping("/deleteDataType")
	@ResponseBody
	public ReturnT<String> deleteDataType(HttpServletRequest request, int id) {
		XxlApiDataType apiDataType = xxlApiDataTypeDao.load(id);
		if (apiDataType == null) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "数据类型ID非法");
		}
		if (!hasBizPermission(request, apiDataType.getBizId())) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "您没有相关业务线的权限,请联系管理员开通");
		}
		// 被其他数据类型引用，拒绝删除
		List<XxlApiDataTypeField> list = xxlApiDataTypeFieldDao.findByFieldDatatypeId(id);
		if (CollectionUtils.isNotEmpty(list)) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "该数据类型被引用中，拒绝删除");
		}
		// 该数据类型被API引用，拒绝删除
		List<XxlApiDocument> apiList = xxlApiDocumentDao.findByResponseDataTypeId(id);
		if (CollectionUtils.isNotEmpty(apiList)) {
			return new ReturnT<String>(ReturnT.FAIL_CODE, "该数据类型被API引用，拒绝删除");
		}
		// delete
		int ret = xxlApiDataTypeDao.delete(id);
		xxlApiDataTypeFieldDao.deleteByParentDatatypeId(id);
		return ret > 0 ? ReturnT.SUCCESS : ReturnT.FAIL;
	}
}
